package com.allen.study.domain.utils.security;

import com.allen.study.test_common.constant.CacheConstants;
import com.allen.study.test_common.exception.CustomRuntimeException;
import com.allen.study.test_common.utils.redis.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName: CustomAuthenticationFailureHandler
 * @Author: AllenSun
 * @Date: 2025/3/18 00:35
 */
@Component
@Slf4j
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {

    @Autowired
    private RedisUtils redisUtils;


    private int maxRetryCount = CacheConstants.PASSWORD_MAX_RETRY_COUNT;

    private Long lockTime = CacheConstants.PASSWORD_LOCK_TIME;


    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        // 认证失败后的自定义逻辑，例如返回错误信息
        // response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        // response.getWriter().write("Authentication failed");
        String username = request.getParameter("username");
        log.info("认证失败：{}",username);
        // 获取登录账户密码错误参数缓存
        String retryCountKey = CacheConstants.PWD_ERR_CNT_KEY + username;
        Integer retryCount = (Integer) redisUtils.get(retryCountKey);
        // 如果是null表示密码错误次数为0
        if (retryCount == null) {
            retryCount = 0;
        }
        // 如果密码错误次数大于等于5次，报错
        if (retryCount >= Integer.valueOf(maxRetryCount).intValue()) {
            String errMsg = String.format("密码输入错误%s次，帐户锁定%s分钟", maxRetryCount, lockTime);
            log.info(errMsg);
            throw new CustomRuntimeException(errMsg);
        }
        // 密码错误次数+1.存入缓存
        retryCount = retryCount + 1;
        redisUtils.set(retryCountKey, retryCount, lockTime, TimeUnit.MINUTES);
        log.info("用户不存在/密码错误");

    }
}
